Coverage Report

Created: 2025-05-07 21:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
D:\a\tools.proto\tools.proto\compiler\src\compiler\protocol.rs
Line
Count
Source
1
// Copyright (c) 2024, BlockProject 3D
2
//
3
// All rights reserved.
4
//
5
// Redistribution and use in source and binary forms, with or without modification,
6
// are permitted provided that the following conditions are met:
7
//
8
//     * Redistributions of source code must retain the above copyright notice,
9
//       this list of conditions and the following disclaimer.
10
//     * Redistributions in binary form must reproduce the above copyright notice,
11
//       this list of conditions and the following disclaimer in the documentation
12
//       and/or other materials provided with the distribution.
13
//     * Neither the name of BlockProject 3D nor the names of its contributors
14
//       may be used to endorse or promote products derived from this software
15
//       without specific prior written permission.
16
//
17
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
21
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
25
// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
26
// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29
use crate::compiler::error::Error;
30
use crate::compiler::imports::Import;
31
use crate::compiler::message::{FieldType, Message};
32
use crate::compiler::r#enum::Enum;
33
use crate::compiler::structure::Structure;
34
use crate::compiler::union::Union;
35
use crate::compiler::util::imports::ImportSolver;
36
use crate::compiler::util::objects::{name_index, ObjectStore};
37
use crate::compiler::util::protocols::ProtocolStore;
38
use crate::compiler::util::types::{Name, TypePathMap};
39
use crate::model::message::MessageFieldValue;
40
use crate::model::protocol::{Description, Endianness};
41
use crate::model::typedef::Typedef;
42
use bp3d_debug::{info, trace};
43
use std::borrow::Cow;
44
use std::collections::BTreeMap;
45
use std::rc::Rc;
46
47
name_index!(Typedef => name);
48
49
#[derive(Clone, Debug)]
50
pub struct Protocol {
51
    pub full_name: String,
52
    pub description: Option<Description>,
53
    pub endianness: Endianness,
54
    pub type_path_map: TypePathMap,
55
    pub structs: ObjectStore<Structure>,
56
    pub messages: ObjectStore<Message>,
57
    pub enums: ObjectStore<Enum>,
58
    pub unions: ObjectStore<Union>,
59
    pub types: ObjectStore<Typedef>,
60
}
61
62
impl bp3d_util::index_map::Index for Protocol {
63
    type Key = str;
64
65
502
    fn index(&self) -> &Self::Key {
66
502
        &self.full_name
67
502
    }
68
}
69
70
impl Protocol {
71
321
    pub fn name(&self) -> &str {
72
321
        if let Some(
id285
) = self.full_name.rfind("::") {
  Branch (72:16): [True: 285, False: 36]
  Branch (72:16): [Folded - Ignored]
73
285
            &self.full_name[id + 2..]
74
        } else {
75
36
            &self.full_name
76
        }
77
321
    }
78
79
323
    pub fn package(&self) -> &str {
80
323
        if let Some(
id285
) = self.full_name.rfind("::") {
  Branch (80:16): [True: 285, False: 38]
  Branch (80:16): [Folded - Ignored]
81
285
            &self.full_name[..id]
82
        } else {
83
38
            ""
84
        }
85
323
    }
86
87
76
    pub fn iter_codecs(&self) -> impl Iterator<Item = &str> {
88
126
        
self.messages76
.
iter76
().
flat_map76
(|v|
v.fields.iter()72
.
filter_map72
(|v| v.codec.as_deref()))
89
76
    }
90
91
130
    pub fn from_model<T: ImportSolver, U>(
92
130
        mut value: crate::model::Protocol,
93
130
        protocols: &ProtocolStore<T, U>,
94
130
        package: &str,
95
130
    ) -> Result<Self, Error> {
96
130
        let full_name = if package.is_empty() {
  Branch (96:28): [True: 18, False: 2]
  Branch (96:28): [Folded - Ignored]
  Branch (96:28): [True: 18, False: 0]
  Branch (96:28): [Folded - Ignored]
  Branch (96:28): [True: 5, False: 0]
  Branch (96:28): [True: 0, False: 72]
  Branch (96:28): [True: 1, False: 0]
  Branch (96:28): [True: 1, False: 0]
  Branch (96:28): [True: 4, False: 0]
  Branch (96:28): [True: 3, False: 0]
  Branch (96:28): [True: 5, False: 0]
  Branch (96:28): [True: 1, False: 0]
97
56
            value.name
98
        } else {
99
74
            format!("{}::{}", package, value.name)
100
        };
101
130
        trace!("Compiling protocol {}", full_name);
102
130
        let mut proto = Protocol {
103
130
            full_name,
104
130
            description: value.description,
105
130
            endianness: value.endianness.unwrap_or(Endianness::Little),
106
130
            type_path_map: TypePathMap::new(),
107
130
            structs: ObjectStore::new(),
108
130
            messages: ObjectStore::new(),
109
130
            enums: ObjectStore::new(),
110
130
            unions: ObjectStore::new(),
111
130
            types: ObjectStore::new(),
112
130
        };
113
130
        info!("Running import solver pass...");
114
130
        if let Some(
mut imports31
) = value.imports {
  Branch (114:16): [True: 6, False: 14]
  Branch (114:16): [Folded - Ignored]
  Branch (114:16): [True: 5, False: 13]
  Branch (114:16): [Folded - Ignored]
  Branch (114:16): [True: 0, False: 5]
  Branch (114:16): [True: 20, False: 52]
  Branch (114:16): [True: 0, False: 1]
  Branch (114:16): [True: 0, False: 1]
  Branch (114:16): [True: 0, False: 4]
  Branch (114:16): [True: 0, False: 3]
  Branch (114:16): [True: 0, False: 5]
  Branch (114:16): [True: 0, False: 1]
115
31
            let mut solved_imports = Vec::new();
116
146
            while let Some(
v115
) = imports.pop() {
  Branch (116:23): [True: 20, False: 6]
  Branch (116:23): [Folded - Ignored]
  Branch (116:23): [True: 19, False: 5]
  Branch (116:23): [Folded - Ignored]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 76, False: 20]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 0, False: 0]
  Branch (116:23): [True: 0, False: 0]
117
115
                let protocol_path = if package.is_empty() || 
v.protocol.contains("::")77
{
  Branch (117:40): [True: 19, False: 1]
  Branch (117:62): [True: 1, False: 0]
  Branch (117:40): [Folded - Ignored]
  Branch (117:62): [Folded - Ignored]
  Branch (117:40): [True: 19, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [Folded - Ignored]
  Branch (117:62): [Folded - Ignored]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 76]
  Branch (117:62): [True: 0, False: 76]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
  Branch (117:40): [True: 0, False: 0]
  Branch (117:62): [True: 0, False: 0]
118
39
                    Cow::Borrowed(&v.protocol)
119
                } else {
120
76
                    Cow::Owned(format!("{}::{}", package, v.protocol))
121
                };
122
115
                trace!({protocol=&**protocol_path} {type=&*v.type_name}, "Solving import");
123
115
                let r = protocols.get(&protocol_path);
124
115
                let r = match r {
125
115
                    Some(r) => r,
126
0
                    None => return Err(Error::UndefinedReference(v.protocol)),
127
                };
128
115
                let ty = r
129
115
                    .structs
130
115
                    .get(&v.type_name)
131
115
                    .map(Import::Struct)
132
115
                    .or_else(|| 
r.messages37
.
get37
(
&v.type_name37
).
map37
(Import::Message))
133
115
                    .or_else(|| 
r.unions18
.
get18
(
&v.type_name18
).
map18
(Import::Union))
134
115
                    .or_else(|| 
r.enums12
.
get12
(
&v.type_name12
).
map12
(Import::Enum))
135
115
                    .or_else(|| 
r.types6
.
get6
(
&v.type_name6
).
map6
(Import::Type))
136
115
                    .ok_or(Error::UnresolvedImport(format!("{}::{}", protocol_path, v.type_name)))
?0
;
137
115
                let type_path = protocols.get_full_type_path(r, &v.type_name).ok_or(Error::SolverError)
?0
;
138
115
                solved_imports.push(ty);
139
480
                let 
count1115
=
imports.iter()115
.
filter115
(|vv| vv.type_name == v.type_name).
count115
();
140
595
                let 
count2115
=
solved_imports.iter()115
.
filter115
(|vv| vv.name() == v.type_name).
count115
();
141
115
                let is_ambiguous = count1 > 0 || 
count2 > 1109
;
  Branch (141:36): [True: 1, False: 19]
  Branch (141:36): [Folded - Ignored]
  Branch (141:36): [True: 1, False: 18]
  Branch (141:36): [Folded - Ignored]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 4, False: 72]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 0, False: 0]
  Branch (141:36): [True: 0, False: 0]
142
115
                proto.type_path_map.add(&ty, type_path);
143
115
                if is_ambiguous {
  Branch (143:20): [True: 2, False: 18]
  Branch (143:20): [Folded - Ignored]
  Branch (143:20): [True: 2, False: 17]
  Branch (143:20): [Folded - Ignored]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 8, False: 68]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 0, False: 0]
  Branch (143:20): [True: 0, False: 0]
144
12
                    trace!({protocol=&**protocol_path} {type=&*v.type_name}, "Import is ambiguous, import it as {}::{}", v.protocol, v.type_name);
145
12
                    ty.insert(format!("{}::{}", v.protocol, v.type_name), &mut proto);
146
103
                } else {
147
103
                    trace!({protocol=&**protocol_path} {type=&*v.type_name}, "Import is not ambiguous");
148
103
                    ty.insert(v.type_name, &mut proto);
149
103
                }
150
            }
151
99
        }
152
130
        info!("Adding typedefs...");
153
130
        if let Some(
types12
) = value.types {
  Branch (153:16): [True: 2, False: 18]
  Branch (153:16): [Folded - Ignored]
  Branch (153:16): [True: 2, False: 16]
  Branch (153:16): [Folded - Ignored]
  Branch (153:16): [True: 0, False: 5]
  Branch (153:16): [True: 8, False: 64]
  Branch (153:16): [True: 0, False: 1]
  Branch (153:16): [True: 0, False: 1]
  Branch (153:16): [True: 0, False: 4]
  Branch (153:16): [True: 0, False: 3]
  Branch (153:16): [True: 0, False: 5]
  Branch (153:16): [True: 0, False: 1]
154
48
            for 
v36
in types {
155
36
                trace!({model=?&v}, "Adding typedef to protocol");
156
36
                proto.types.insert(Rc::new(v));
157
36
            }
158
118
        }
159
130
        info!("Running type inference pass...");
160
130
        if let Some(
structs111
) = &mut value.structs {
  Branch (160:16): [True: 17, False: 3]
  Branch (160:16): [Folded - Ignored]
  Branch (160:16): [True: 16, False: 2]
  Branch (160:16): [Folded - Ignored]
  Branch (160:16): [True: 0, False: 5]
  Branch (160:16): [True: 64, False: 8]
  Branch (160:16): [True: 1, False: 0]
  Branch (160:16): [True: 1, False: 0]
  Branch (160:16): [True: 4, False: 0]
  Branch (160:16): [True: 3, False: 0]
  Branch (160:16): [True: 5, False: 0]
  Branch (160:16): [True: 0, False: 1]
161
307
            for 
v196
in structs {
162
565
                for 
field369
in &mut v.fields {
163
0
                    if let Some(info) =
  Branch (163:28): [True: 0, False: 60]
  Branch (163:28): [Folded - Ignored]
  Branch (163:28): [True: 0, False: 59]
  Branch (163:28): [Folded - Ignored]
  Branch (163:28): [True: 0, False: 0]
  Branch (163:28): [True: 0, False: 236]
  Branch (163:28): [True: 0, False: 1]
  Branch (163:28): [True: 0, False: 1]
  Branch (163:28): [True: 0, False: 4]
  Branch (163:28): [True: 0, False: 2]
  Branch (163:28): [True: 0, False: 6]
  Branch (163:28): [True: 0, False: 0]
164
369
                        field.item_type.as_ref().and_then(|v| 
proto.types37
.
get37
(
v37
)).and_then(|v|
v0
.
to_struct0
())
165
0
                    {
166
0
                        trace!({typedef=?info}, "Inferred {} as {}", field.name, info.name);
167
0
                        let name = std::mem::replace(field, info.clone()).name;
168
0
                        field.name = name;
169
369
                    }
170
                }
171
            }
172
19
        }
173
130
        if let Some(
messages60
) = &mut value.messages {
  Branch (173:16): [True: 10, False: 10]
  Branch (173:16): [Folded - Ignored]
  Branch (173:16): [True: 8, False: 10]
  Branch (173:16): [Folded - Ignored]
  Branch (173:16): [True: 5, False: 0]
  Branch (173:16): [True: 32, False: 40]
  Branch (173:16): [True: 0, False: 1]
  Branch (173:16): [True: 0, False: 1]
  Branch (173:16): [True: 0, False: 4]
  Branch (173:16): [True: 0, False: 3]
  Branch (173:16): [True: 5, False: 0]
  Branch (173:16): [True: 0, False: 1]
174
171
            for 
v111
in messages {
175
297
                for 
field186
in &mut v.fields {
176
36
                    if let Some(info) =
  Branch (176:28): [True: 6, False: 30]
  Branch (176:28): [Folded - Ignored]
  Branch (176:28): [True: 6, False: 21]
  Branch (176:28): [Folded - Ignored]
  Branch (176:28): [True: 0, False: 6]
  Branch (176:28): [True: 24, False: 84]
  Branch (176:28): [True: 0, False: 0]
  Branch (176:28): [True: 0, False: 0]
  Branch (176:28): [True: 0, False: 0]
  Branch (176:28): [True: 0, False: 0]
  Branch (176:28): [True: 0, False: 9]
  Branch (176:28): [True: 0, False: 0]
177
186
                        field.item_type.as_ref().and_then(|v| 
proto.types84
.
get84
(
v84
)).and_then(|v|
v36
.
to_message36
())
178
36
                    {
179
36
                        trace!({typedef=?info}, "Inferred {} as {}", field.name, info.name);
180
36
                        let name = std::mem::replace(field, info.clone()).name;
181
36
                        field.name = name;
182
150
                    }
183
                }
184
            }
185
70
        }
186
130
        info!("Running compiler pass...");
187
130
        if let Some(
enums19
) = value.enums {
  Branch (187:16): [True: 3, False: 17]
  Branch (187:16): [Folded - Ignored]
  Branch (187:16): [True: 3, False: 15]
  Branch (187:16): [Folded - Ignored]
  Branch (187:16): [True: 0, False: 5]
  Branch (187:16): [True: 12, False: 60]
  Branch (187:16): [True: 0, False: 1]
  Branch (187:16): [True: 0, False: 1]
  Branch (187:16): [True: 0, False: 4]
  Branch (187:16): [True: 0, False: 3]
  Branch (187:16): [True: 0, False: 5]
  Branch (187:16): [True: 1, False: 0]
188
19
            trace!(">> Compiling enums...");
189
37
            for 
v19
in enums {
190
19
                trace!({model=?&v}, "Compiling enum");
191
19
                let 
v18
=
Rc::new18
(Enum::from_model(v)
?1
);
192
18
                proto.enums.insert(v);
193
            }
194
111
        }
195
129
        if let Some(
structs111
) = value.structs {
  Branch (195:16): [True: 17, False: 3]
  Branch (195:16): [Folded - Ignored]
  Branch (195:16): [True: 16, False: 2]
  Branch (195:16): [Folded - Ignored]
  Branch (195:16): [True: 0, False: 5]
  Branch (195:16): [True: 64, False: 8]
  Branch (195:16): [True: 1, False: 0]
  Branch (195:16): [True: 1, False: 0]
  Branch (195:16): [True: 4, False: 0]
  Branch (195:16): [True: 3, False: 0]
  Branch (195:16): [True: 5, False: 0]
  Branch (195:16): [True: 0, False: 0]
196
111
            trace!(">> Compiling structures...");
197
298
            for 
v196
in structs {
198
196
                trace!({model=?&v}, "Compiling structure");
199
196
                let 
v187
=
Rc::new187
(Structure::from_model(&proto, v)
?9
);
200
187
                proto.structs.insert(v);
201
            }
202
18
        }
203
120
        let mut union_messages = BTreeMap::new();
204
120
        if let Some(
mut messages60
) = value.messages {
  Branch (204:16): [True: 10, False: 10]
  Branch (204:16): [Folded - Ignored]
  Branch (204:16): [True: 8, False: 10]
  Branch (204:16): [Folded - Ignored]
  Branch (204:16): [True: 5, False: 0]
  Branch (204:16): [True: 32, False: 40]
  Branch (204:16): [True: 0, False: 0]
  Branch (204:16): [True: 0, False: 0]
  Branch (204:16): [True: 0, False: 0]
  Branch (204:16): [True: 0, False: 0]
  Branch (204:16): [True: 5, False: 0]
  Branch (204:16): [True: 0, False: 0]
205
60
            trace!(">> Extracting unions and messages with references to unions...");
206
60
            let len = messages.len();
207
111
            for i in 1..
len + 160
{
208
111
                let i = len - i;
209
186
                let 
has_unions111
=
messages[i].fields.iter()111
.
any111
(|v| match &v.value {
210
48
                    None => false,
211
138
                    Some(v) => 
matches!121
(v, MessageFieldValue::Union { .. }),
212
186
                });
213
111
                if has_unions {
  Branch (213:20): [True: 2, False: 18]
  Branch (213:20): [Folded - Ignored]
  Branch (213:20): [True: 2, False: 14]
  Branch (213:20): [Folded - Ignored]
  Branch (213:20): [True: 0, False: 6]
  Branch (213:20): [True: 8, False: 56]
  Branch (213:20): [True: 0, False: 0]
  Branch (213:20): [True: 0, False: 0]
  Branch (213:20): [True: 0, False: 0]
  Branch (213:20): [True: 0, False: 0]
  Branch (213:20): [True: 5, False: 0]
  Branch (213:20): [True: 0, False: 0]
214
17
                    let msg = messages.remove(i);
215
17
                    union_messages.insert(i, msg);
216
94
                }
217
            }
218
60
            let pos = len;
219
60
            let len = messages.len();
220
94
            for i in 1..
len + 160
{
221
94
                let i = len - i;
222
94
                let has_ref = union_messages.values().any(|union| 
messages[i]18
.
references18
(
&union.name18
));
223
94
                if has_ref {
  Branch (223:20): [True: 1, False: 17]
  Branch (223:20): [Folded - Ignored]
  Branch (223:20): [True: 1, False: 13]
  Branch (223:20): [Folded - Ignored]
  Branch (223:20): [True: 0, False: 6]
  Branch (223:20): [True: 4, False: 52]
  Branch (223:20): [True: 0, False: 0]
  Branch (223:20): [True: 0, False: 0]
  Branch (223:20): [True: 0, False: 0]
  Branch (223:20): [True: 0, False: 0]
  Branch (223:20): [True: 0, False: 0]
  Branch (223:20): [True: 0, False: 0]
224
6
                    let msg = messages.remove(i);
225
6
                    union_messages.insert(pos + i, msg);
226
88
                }
227
            }
228
60
            trace!(">> Compiling messages with no references to unions...");
229
143
            for 
v88
in messages {
230
88
                trace!({model=?&v}, "Compiling message");
231
88
                let 
v83
=
Rc::new83
(Message::from_model(&proto, v)
?5
);
232
83
                proto.messages.insert(v);
233
            }
234
60
        }
235
115
        if let Some(
unions22
) = value.unions {
  Branch (235:16): [True: 3, False: 17]
  Branch (235:16): [Folded - Ignored]
  Branch (235:16): [True: 3, False: 15]
  Branch (235:16): [Folded - Ignored]
  Branch (235:16): [True: 0, False: 0]
  Branch (235:16): [True: 12, False: 60]
  Branch (235:16): [True: 0, False: 0]
  Branch (235:16): [True: 0, False: 0]
  Branch (235:16): [True: 0, False: 0]
  Branch (235:16): [True: 0, False: 0]
  Branch (235:16): [True: 4, False: 1]
  Branch (235:16): [True: 0, False: 0]
236
22
            trace!(">> Compiling unions...");
237
44
            for 
v22
in unions {
238
22
                trace!({model=?&v}, "Compiling union");
239
22
                let v = Rc::new(Union::from_model(&proto, v)
?0
);
240
22
                proto.unions.insert(v);
241
            }
242
93
        }
243
115
        trace!(">> Compiling messages with references to unions...");
244
133
        for (_, 
msg23
) in union_messages {
245
23
            trace!({model=?&msg}, "Compiling message");
246
23
            let 
v18
=
Rc::new18
(Message::from_model(&proto, msg)
?5
);
247
18
            proto.messages.insert(v);
248
        }
249
250
110
        info!("Running list sanitizer pass...");
251
110
        for 
msg100
in proto.messages.iter() {
252
100
            if msg.is_embedded() {
  Branch (252:16): [True: 4, False: 16]
  Branch (252:16): [Folded - Ignored]
  Branch (252:16): [True: 4, False: 12]
  Branch (252:16): [Folded - Ignored]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 16, False: 48]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 0, False: 0]
  Branch (252:16): [True: 0, False: 0]
253
48
                for field in &
msg.fields24
{
254
48
                    let flag = match &field.ty {
255
6
                        FieldType::Container(v) => v.nested,
256
42
                        _ => true,
257
                    };
258
48
                    if !flag {
  Branch (258:24): [True: 0, False: 8]
  Branch (258:24): [Folded - Ignored]
  Branch (258:24): [True: 0, False: 8]
  Branch (258:24): [Folded - Ignored]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 32]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 0]
  Branch (258:24): [True: 0, False: 0]
259
0
                        return Err(Error::MissingNestedList(format!("{}::{}", msg.name, field.name)));
260
48
                    }
261
                }
262
76
            }
263
        }
264
110
        Ok(proto)
265
130
    }
266
}